package jatosoft.accounting.dao.model;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Transient;

@Entity
public class Voucher extends BaseModel {
	private static final long serialVersionUID = 6989787794425379220L;
	private Date voucherDate;
	private List<VoucherItem> voucherItemList = new ArrayList<VoucherItem>();
	private Double creditBalance = 0.0;
	private Double debitBalance = 0.0;
	private String desc;

	public Voucher(int size) {
		for (int i = 0; i < size; i++) {
			addItem(new VoucherItem(new Account()));
		}
	}

	public Voucher() {
	}

	public Date getVoucherDate() {
		return voucherDate;
	}

	public void setVoucherDate(Date voucherDate) {
		this.voucherDate = voucherDate;
	}

	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
	@JoinColumn(name = "VOUCHER_ID")
	public List<VoucherItem> getVoucherItemList() {
		return voucherItemList;
	}

	public void setVoucherItemList(List<VoucherItem> voucherItemList) {
		this.voucherItemList = voucherItemList;
	}

	@Id
	@Column(name = "VOUCHER_ID")
	@GeneratedValue(strategy = GenerationType.AUTO)
	public Integer getId() {
		return id;
	}

	public Double getCreditBalance() {
		return creditBalance;
	}

	public void setCreditBalance(Double creditBalance) {
		this.creditBalance = creditBalance;
	}

	public Double getDebitBalance() {
		return debitBalance;
	}

	public void setDebitBalance(Double debitBalance) {
		this.debitBalance = debitBalance;
	}

	@Column(name = "V_DESC")
	public String getDesc() {
		return desc;
	}

	public void setDesc(String desc) {
		this.desc = desc;
	}

	@Override
	public String toString() {
		StringBuilder builder = new StringBuilder();
		builder.append("Voucher [creditBalance=");
		builder.append(creditBalance);
		builder.append(", debitBalance=");
		builder.append(debitBalance);
		builder.append(", id=");
		builder.append(id);
		builder.append(", voucherDate=");
		builder.append(voucherDate);
		builder.append(", voucherItemList=");
		builder.append(voucherItemList);
		builder.append("]");
		return builder.toString();
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Voucher other = (Voucher) obj;
		if (id == null) {
			if (other.id != null)
				return false;
		} else if (!id.equals(other.id))
			return false;
		return true;
	}

	public int compareTo(Voucher o) {
		if (o == null) {
			return 1;
		}
		if (id == null) {
			return -1;
		}
		if (o.id == null) {
			return 1;
		}

		return id > o.id ? 1 : -1;
	}

	public Voucher clone() {
		Voucher v = new Voucher();
		v.setId(id);
		v.setCreditBalance(creditBalance);
		v.setDebitBalance(debitBalance);
		v.setDesc(desc);
		v.setVoucherDate(voucherDate);
		List<VoucherItem> l = new ArrayList<VoucherItem>();
		for (VoucherItem vi : voucherItemList) {
			l.add(vi.clone());
		}
		v.setVoucherItemList(l);
		return v;
	}

	public void addItem(VoucherItem vi) {
		if (voucherItemList == null) {
			voucherItemList = new ArrayList<VoucherItem>();
		}
		vi.setCreationDate(creationDate);
		vi.setCreator(creator);
		vi.setModificationDate(modificationDate);
		vi.setModifier(modifier);
		vi.setSeq(voucherItemList.size() + 1);
		vi.setVoucher(this);
		if (vi.getItem() == null || "".equals(vi.getItem())) {
			vi.setItem(desc);
		}
		if (vi.getAmount() > 0) {
			creditBalance += vi.getAmount();
		} else {
			debitBalance += vi.getAmount()*-1;
		}
		voucherItemList.add(vi);

	}

	public int size() {
		return voucherItemList == null ? 0 : voucherItemList.size();
	}

	public VoucherItem getVoucherItem(int i) {
		return voucherItemList.get(i);
	}

	public void removeVoucherItem(int i) {
		voucherItemList.remove(i);
	}

	public void cleanVoucherItemList() {
		for (int i = 0; i < size();) {
			if (getVoucherItem(i).getAmount() == 0.0) {
				removeVoucherItem(i);
				if (i < size()) {
					getVoucherItem(i).setSeq(i + 1);
				}
			} else {
				i++;
			}
		}
	}

	@Transient
	public boolean isEmpty() {
		return size() == 0 ? true : false;
	}

	@Override
	public void setCreationDate(Date creationDate) {
		super.setCreationDate(creationDate);
		if (voucherItemList != null) {
			for (VoucherItem item : voucherItemList) {
				item.setCreationDate(creationDate);
			}
		}
	}

	@Override
	public void setCreator(String creator) {
		super.setCreator(creator);
		if (voucherItemList != null) {
			for (VoucherItem item : voucherItemList) {
				item.setCreator(creator);
			}
		}
	}

	@Override
	public void setModificationDate(Date modificationDate) {
		super.setModificationDate(modificationDate);
		if (voucherItemList != null) {
			for (VoucherItem item : voucherItemList) {
				item.setModificationDate(modificationDate);
			}
		}
	}

	@Override
	public void setModifier(String modifier) {
		super.setModifier(modifier);
		if (voucherItemList != null) {
			for (VoucherItem item : voucherItemList) {
				item.setModifier(modifier);
			}
		}
	}
	
	public Voucher copy(){
		Voucher v = new Voucher();
		v.setCreditBalance(creditBalance);
		v.setDebitBalance(debitBalance);
		v.setDesc(desc);
		for (VoucherItem vi : voucherItemList) {
			v.addItem(vi.copy());
		}
		
		return v;
	}
}
